package com.runchamp;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.internal.app.WindowDecorActionBar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.getbase.floatingactionbutton.FloatingActionButton;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.JsonHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import com.runchamp.util.DistanceCircleView;

import org.json.JSONArray;
import org.json.JSONObject;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;

public class RaceInfo extends ActionBarActivity {
    public String path = "http://runtobo.appspot.com/racesManager";
    public de.hdodenhof.circleimageview.CircleImageView circle;
    private Intent intentInvite;
    private JSONAdapterParticipantsList mJSONAdapter;
    private Bundle race;
    private boolean isUserInRace = false;
    private boolean isUserReady = false;
    private TextView timeRemains;
    private RequestParams params;
    private TextView numParticipants;
    private TextView mainButtonTextView;
    private TextView readyButtonTextView;
    private String raceManager;
    private TextView timerMessageTextView;
    private FloatingActionButton startRaceButton;
    private FloatingActionButton readyButton;
    private BroadcastReceiver myReceiver = null;
    private Boolean myReceiverIsRegistered = false;
    private long user;
    private Calendar nowDate;
    private Calendar raceDate;
    private CountDownTimer cntTimer;
    private long totalTimeDelta;
    private long managerTimeDelta;
    private String startingString;
    private boolean startedRace = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_race_info);

        /*
        * loads the user prefs*/
        SharedPreferences prefs = getSharedPreferences("MyPrefsFile", Context.MODE_PRIVATE);

        /*fields initialize*/
        user = Long.valueOf(prefs.getString("userID", ""));
        startingString = "";
        mainButtonTextView = (TextView) findViewById(R.id.mainButtonText);
        readyButtonTextView = (TextView) findViewById(R.id.readyButtonText);
        TextView tags = (TextView) findViewById(R.id.tags);
        TextView manager = (TextView) findViewById(R.id.manager);
        TextView distance = (TextView) findViewById(R.id.text_distance);
        TextView time = (TextView) findViewById(R.id.time);
        timeRemains = (TextView) findViewById(R.id.timeLeft);
        TextView estimatedTime = (TextView) findViewById(R.id.text_estimated_time);
        nowDate = Calendar.getInstance();
        raceDate = Calendar.getInstance();
        numParticipants = (TextView) findViewById(R.id.num_participants);
        timerMessageTextView = (TextView) findViewById(R.id.timer_message);
        circle = (de.hdodenhof.circleimageview.CircleImageView) findViewById(R.id.row_circle);
        race = this.getIntent().getExtras();
        tags.setText(race.getString("Tags"));
        raceManager = race.getString("Manager");
        manager.setText(raceManager);
        DistanceCircleView.setCircle(race.getString("Distance"), circle, distance, (TextView) findViewById(R.id.text_km));
        numParticipants.setText(race.getString("Participants"));
        String estPace = String.format("%.1f ", Float.parseFloat(race.getString("Estimated")) / Float.parseFloat(race.getString("Distance")));
        estimatedTime.setText(estPace + " min/km");
        String raceDAteFormat = race.getString("Time");
        int raceYear = Integer.valueOf(raceDAteFormat.substring(0, 4));
        int raceMonth = Integer.valueOf(raceDAteFormat.substring(5, 7));

        raceMonth--; //notice that january is 0 and not 1 as the text
        int raceDay = Integer.valueOf(raceDAteFormat.substring(8, 10));
        int raceHour = Integer.valueOf(raceDAteFormat.substring(11, 13));
        int raceMin = Integer.valueOf(raceDAteFormat.substring(14, 16));
        int raceSec = Integer.valueOf(raceDAteFormat.substring(17, 19));
        time.setText(String.format("%02d:%02d %d.%d.%d", raceHour, raceMin, raceDay, raceMonth + 1, raceYear));

        /*date and time set up*/
        raceDate.set(Calendar.YEAR, raceYear);
        raceDate.set(Calendar.MONTH, raceMonth);
        raceDate.set(Calendar.DAY_OF_MONTH, raceDay);
        raceDate.set(Calendar.HOUR_OF_DAY, raceHour);
        raceDate.set(Calendar.MINUTE, raceMin);
        raceDate.set(Calendar.SECOND, raceSec);

        int hourDelta = raceDate.get(Calendar.HOUR_OF_DAY) - nowDate.get(Calendar.HOUR_OF_DAY);
        int minDelta = raceDate.get(Calendar.MINUTE) - nowDate.get(Calendar.MINUTE);
        int secDelta = raceDate.get(Calendar.SECOND) - nowDate.get(Calendar.SECOND);

        totalTimeDelta = (hourDelta * 60 * 60 + minDelta * 60 + secDelta + 2) * 1000;
        if (raceDate.get(Calendar.YEAR) == nowDate.get(Calendar.YEAR)
                && raceDate.get(Calendar.MONTH) == nowDate.get(Calendar.MONTH)
                && raceDate.get(Calendar.DAY_OF_MONTH) == nowDate.get(Calendar.DAY_OF_MONTH)
                && totalTimeDelta > 0) {
            timerMessageTextView.setVisibility(View.VISIBLE);
            cntTimer = new CountDownTimer(totalTimeDelta, 1000) {
                @Override
                public void onTick(long millisUntilFinished) {
                    timeRemains.setText(updateTimeLeft(raceDate));
                }

                @Override
                public void onFinish() {
                    timerMessageTextView.setText("STARTING RACE...");
                }
            }.start();
        }

        Date startTime;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            startTime = sdf.parse(race.getString("Time"));
        } catch (ParseException e) {
            startTime = new Date();
            e.printStackTrace();
        }


        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date date = new Date();
        dateFormat.format(date);

        final Handler handler = new Handler();
        Timer startButtonTimer = new Timer();
        startRaceButton = (FloatingActionButton) findViewById(R.id.normal_plus);
        readyButton = (FloatingActionButton) findViewById(R.id.ready_button);

        /*startButtonTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        startRaceButton = (FloatingActionButton) findViewById(R.id.normal_plus);
                       // startRaceButton.setIcon(R.drawable.ic_action_play);
                    }
                });
            }
        },startTime);
*/
        intentInvite = new Intent(this, InviteFriends.class);

        /*notification settings*/
        myReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                AsyncHttpClient client = new AsyncHttpClient();
                client.get(String.format("%s/participants?race=%s", path, race.getString("Key")),
                        new JsonHttpResponseHandler() {

                            @Override
                            public void onSuccess(JSONArray jsonObject) {
                                updateParticipantsList(jsonObject);
                            }

                            @Override
                            public void onFailure(int statusCode, Throwable throwable, JSONObject error) {
                                Toast.makeText(getApplicationContext(), "Fail", Toast.LENGTH_LONG).show();
                            }
                        });
            }
        };
        IntentFilter updateReadyFilter = new IntentFilter();
        updateReadyFilter.addAction("com.runchamp.RACER_READY");
        registerReceiver(myReceiver, updateReadyFilter);

        /*get and present participants list*/
        AsyncHttpClient client = new AsyncHttpClient();
        ListView participantsListView;
        mJSONAdapter = new JSONAdapterParticipantsList(this, getLayoutInflater());
        participantsListView = (ListView) findViewById(R.id.participants_listview);
        participantsListView.setAdapter(mJSONAdapter);
        client.get(String.format("%s/participants?race=%s", path, race.getString("Key")),
                new JsonHttpResponseHandler() {

                    @Override
                    public void onSuccess(JSONArray jsonObject) {
                        updateParticipantsList(jsonObject);
                    }

                    @Override
                    public void onFailure(int statusCode, Throwable throwable, JSONObject error) {
                        Toast.makeText(getApplicationContext(), "Fail", Toast.LENGTH_LONG).show();
                    }
                });


        android.support.v7.app.ActionBar actionBar = getSupportActionBar();
        WindowDecorActionBar bar = (WindowDecorActionBar) actionBar;
        bar.setDisplayHomeAsUpEnabled(true);
        bar.setHomeButtonEnabled(true);
        actionBar.setHomeButtonEnabled(true);
        actionBar.setDisplayHomeAsUpEnabled(true);

        actionBar.show();
        bar.show();
        setCentralButtonIcon();
        setReadyButton();
    }

    //it seems we don't need it but maybe we decide to change the timer settings and then we would want to use it
    private void waitingForManagerTimer() {
        final Calendar newStartTime = (Calendar) raceDate.clone();
        newStartTime.add(Calendar.MINUTE, 2);

        int hourDeltaManager = newStartTime.get(Calendar.HOUR_OF_DAY) - nowDate.get(Calendar.HOUR_OF_DAY);
        int minDeltaManager = newStartTime.get(Calendar.MINUTE) - nowDate.get(Calendar.MINUTE);
        int secDeltaManager = newStartTime.get(Calendar.SECOND) - nowDate.get(Calendar.SECOND);


        managerTimeDelta = (hourDeltaManager * 60 * 60 + minDeltaManager * 60 + secDeltaManager + 2) * 1000;
        if (managerTimeDelta > 0 && managerTimeDelta < 130000) {
            if (!raceManager.equals("God")) {
                timeRemains.setTextColor(Color.BLACK);
                timerMessageTextView.setText("MANAGER CAN START RACE");
                timerMessageTextView.setVisibility(View.VISIBLE);
                timeRemains.setVisibility(View.VISIBLE);


                cntTimer = new CountDownTimer(managerTimeDelta, 1000) {
                    @Override
                    public void onTick(long millisUntilFinished) {
                        timeRemains.setText(updateTimeLeft(newStartTime));
                    }

                    @Override
                    public void onFinish() {
                        timeRemains.setVisibility(View.GONE);
                        timerMessageTextView.setText("STARTING RACE...");


                    }
                }.start();

            } else {
                timeRemains.setVisibility(View.GONE);
                timerMessageTextView.setText("STARTING RACE...");

            }
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        SharedPreferences prefs = getSharedPreferences("MyPrefsFile", Context.MODE_PRIVATE);
        user = Long.valueOf(prefs.getString("userID", ""));

        if (!myReceiverIsRegistered) {
            IntentFilter updateReadyFilter = new IntentFilter();
            updateReadyFilter.addAction("com.runchamp.RACER_READY");
            registerReceiver(myReceiver, updateReadyFilter);
            myReceiverIsRegistered = true;
        }

        //starts the timer again
        int hourDelta = raceDate.get(Calendar.HOUR_OF_DAY) - nowDate.get(Calendar.HOUR_OF_DAY);
        int minDelta = raceDate.get(Calendar.MINUTE) - nowDate.get(Calendar.MINUTE);
        int secDelta = raceDate.get(Calendar.SECOND) - nowDate.get(Calendar.SECOND);
        totalTimeDelta = (hourDelta * 60 * 60 + minDelta * 60 + secDelta + 2) * 1000;
        if (cntTimer == null) {
            if (raceDate.get(Calendar.YEAR) == nowDate.get(Calendar.YEAR)
                    && raceDate.get(Calendar.MONTH) == nowDate.get(Calendar.MONTH)
                    && raceDate.get(Calendar.DAY_OF_MONTH) == nowDate.get(Calendar.DAY_OF_MONTH)
                    && totalTimeDelta > 0) {
                timerMessageTextView.setVisibility(View.VISIBLE);
                cntTimer = new CountDownTimer(totalTimeDelta, 1000) {
                    @Override
                    public void onTick(long millisUntilFinished) {
                        timeRemains.setText(updateTimeLeft(raceDate));
                    }

                    @Override
                    public void onFinish() {
                    }
                }.start();
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (cntTimer != null) {
            cntTimer.cancel();
            cntTimer = null;
        }
        if (myReceiverIsRegistered) {
            unregisterReceiver(myReceiver);
            myReceiverIsRegistered = false;
        }
    }

    @Override
    protected void onDestroy() {
        this.overridePendingTransition(R.anim.nothing, R.anim.slide_out_right);
        super.onDestroy();
        if (cntTimer != null) {
            cntTimer.cancel();
            cntTimer = null;
        }
        if (myReceiverIsRegistered) {
            unregisterReceiver(myReceiver);
            myReceiverIsRegistered = false;
        }
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_race_info, menu);
        if (true) {
            MenuItem joinAction = (MenuItem) menu.findItem(R.id.action_join);
            joinAction.setVisible(false);
        }
        if (true) {
            MenuItem readyAction = (MenuItem) menu.findItem(R.id.action_ready);
            MenuItem leaveAction = (MenuItem) menu.findItem(R.id.action_leave);
            readyAction.setVisible(false);
            leaveAction.setVisible(false);
        }

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.

        switch (item.getItemId()) {
            case 16908332:
                finish();
                this.overridePendingTransition(R.anim.nothing, R.anim.slide_out_right);
                return true;
            case R.id.action_join:
                joinRace();
                return true;
            case R.id.action_ready:
                userIsReady();
                return true;
            case R.id.action_invite:
                intentInvite.putExtras(race);
                startActivity(intentInvite);

                return true;
            case R.id.action_leave:
                leaveRace();
                return true;
            case R.id.action_bar_root:
                finish();
                this.overridePendingTransition(R.anim.nothing, R.anim.slide_out_right);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    /*adds this user to that race*/
    public void joinRace() {
        AsyncHttpClient client = new AsyncHttpClient();
        params = new RequestParams();
        params.put("user", String.valueOf(user));
        params.put("race", race.getString("Key"));

        client.post(String.format("%s/addUserToRace", path), params, new JsonHttpResponseHandler() {

            @Override
            public void onSuccess(JSONArray jsonObject) {
                updateParticipantsList(jsonObject);
                Toast.makeText(getApplicationContext(), "Press when you're ready!", Toast.LENGTH_LONG).show();
            }

            @Override
            public void onFailure(int statusCode, Throwable throwable, JSONObject error) {
                Toast.makeText(getApplicationContext(), "Failed to Join race", Toast.LENGTH_LONG).show();
            }
        });

    }

    /*removes this user from that race*/
    public void leaveRace() {
        AsyncHttpClient client = new AsyncHttpClient();
        params = new RequestParams();
        params.put("user", String.valueOf(user));
        params.put("race", race.getString("Key"));

        client.post(String.format("%s/removeUserFromRace", path), params, new JsonHttpResponseHandler() {

            @Override
            public void onSuccess(JSONArray jsonObject) {
                updateParticipantsList(jsonObject);
                Toast.makeText(getApplicationContext(), "Left successfully!", Toast.LENGTH_LONG).show();
            }

            @Override
            public void onFailure(int statusCode, Throwable throwable, JSONObject error) {
                Toast.makeText(getApplicationContext(), "Failed to leave race", Toast.LENGTH_LONG).show();
            }
        });

    }

    /*signals that the user is ready for racing*/
    public void userIsReady() {
        AsyncHttpClient client = new AsyncHttpClient();
        params = new RequestParams();
        params.put("user", String.valueOf(user));
        params.put("race", race.getString("Key"));

        client.post(String.format("%s/userIsReady", path), params, new JsonHttpResponseHandler() {

            @Override
            public void onSuccess(JSONArray jsonObject) {
                updateParticipantsList(jsonObject);
                Toast.makeText(getApplicationContext(), "you're ready!", Toast.LENGTH_LONG).show();
            }

            @Override
            public void onFailure(int statusCode, Throwable throwable, JSONObject error) {
                Toast.makeText(getApplicationContext(), "Failed to declare ready", Toast.LENGTH_LONG).show();
            }

        });
    }

    public void startRace(View view) {
        if (!startedRace) {
            startedRace = true;
            params = new RequestParams();
            params.put("key", race.getString("Key"));
            AsyncHttpClient client = new AsyncHttpClient();
            client.post("http://runtobo.appspot.com/liverace/startRace", params, new JsonHttpResponseHandler() {

                @Override
                public void onSuccess(JSONArray jsonObject) {
                    Toast.makeText(getApplicationContext(), "Starting Race!", Toast.LENGTH_LONG).show();
                }

                @Override
                public void onFailure(int statusCode, Throwable throwable, JSONObject error) {
                    Toast.makeText(getApplicationContext(), "Failed to start race", Toast.LENGTH_LONG).show();
                }
            });
        }
    }


    public String updateTimeLeft(Calendar raceDate) {
        nowDate = Calendar.getInstance();
        int raceHour = raceDate.get(Calendar.HOUR_OF_DAY);
        int nowHour = nowDate.get(Calendar.HOUR_OF_DAY);
        int raceMin = raceDate.get(Calendar.MINUTE);
        int nowMin = nowDate.get(Calendar.MINUTE);
        int raceSec = raceDate.get(Calendar.SECOND);
        int nowSec = nowDate.get(Calendar.SECOND);
        String res = "";
        int secs = raceSec - nowSec;
        int mins = raceMin - nowMin;
        int hours = raceHour - nowHour;
        if (hours == 0 && mins == 1)
            timeRemains.setTextColor(Color.RED);
        if (hours < 0) return startingString;
        if (secs < 0) {
            secs = 60 + (secs);
            mins--;
            if (mins < 0) {
                mins = 60 + (mins);
                hours--;
                if (hours < 0) {
                    res = startingString;
                    return res;
                }

            }
        }
        if (mins < 0) {
            mins = 60 + (mins);
            hours--;
            if (hours < 0) {
                res = startingString;
                return res;
            }
        }

        String h0, m0, s0;
        h0 = m0 = s0 = "";
        if (hours < 10) h0 = "0";
        if (mins < 10) m0 = "0";
        if (secs < 10) s0 = "0";

        res = String.format("%s%d:%s%d:%s%d", h0, hours, m0, mins, s0, secs);
        return res;
    }

    @Override
    public void onBackPressed() {
        if (cntTimer != null) {
            cntTimer.cancel();
            cntTimer = null;
        }
        finish();
        this.overridePendingTransition(R.anim.nothing, R.anim.slide_out_right);
    }

    private void updateParticipantsList(JSONArray jsonObject) {
        mJSONAdapter.updateData(jsonObject);
        isUserInRace = mJSONAdapter.isUserInRace(jsonObject, user);
        isUserReady = mJSONAdapter.isUserReady(jsonObject, user);
        numParticipants.setText(String.valueOf(mJSONAdapter.getCount()));
        invalidateOptionsMenu();
        setCentralButtonIcon();
        setReadyButton();
    }


    public void centralButtonClicked(View view) {
        setCentralButtonIcon();
        setReadyButton();
        if (!isUserInRace) {
            joinRace();

        } else {
            leaveRace();
        }

    }

    public void readyButtonClicked(View view) {
        setCentralButtonIcon();
        setReadyButton();
        if (!isUserReady) {
            userIsReady();

        }
    }


    public void setReadyButton() {

        if (!isUserReady) {
            //startRaceButton.setIcon(R.drawable.ic_action_done);
            readyButtonTextView.setText("Ready");
            if (isUserInRace)
                readyButton.setColorNormal(Color.parseColor("#669900"));
            else
                readyButton.setColorNormal(Color.parseColor("#BDBDBD"));
        } else {
            readyButton.setColorNormal(Color.parseColor("#BDBDBD"));
        }
    }

    public void setCentralButtonIcon() {
        if (!isUserInRace) {
            //startRaceButton.setIcon(R.drawable.running_hdpi);
            mainButtonTextView.setText("Join");
            startRaceButton.setColorNormal(Color.parseColor("#3F51B5"));
        } else {
            //startRaceButton.setIcon(R.drawable.no_running);
            mainButtonTextView.setText("Leave");
            startRaceButton.setColorNormal(Color.parseColor("#B71C1C"));
        }
    }

}
